/*
 * This file is part of Shopping Lists Organizer software
 *
 * Copyright (C) 2011 Denis Kvita <dkvita@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include <QtGui>
#include <QtSql>

#include "shoppinglistmodel.h"

shoppingListModel::shoppingListModel(QObject *parent) :
	QAbstractTableModel(parent),cc()
{
	fieldNames<<"pDate"<<"pList"<<"pCnt"<<"pCostP"<<"pCost"<<"pJoy"<<"pDone";
}

int shoppingListModel::rowCount(const QModelIndex &parent) const
{
	return cc.count();
}

int shoppingListModel::columnCount(const QModelIndex &parent) const
{
	return 6;
}

QVariant shoppingListModel::data(const QModelIndex &index, int role) const
{
	if(role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::CheckStateRole){
//		QSqlRecord *rcd;
//		QVariant v;
//		rcd= cc.at(index.row());

//		v= rcd->value(index.column());
		if(role == Qt::CheckStateRole){
//			v= rcd->value(6);
			if(index.column() == 1) return cc.value(index.row()).value(6).toDouble() == 1 ? Qt::Checked : cc.value(index.row()).value(6).toDouble() == 0 ? Qt::Unchecked : Qt::PartiallyChecked;
		}else{
			if(index.column() == 0) return cc.value(index.row()).value(index.column()).toDate();
			if(index.column() == 3 || index.column() == 4){
				double n= cc.value(index.row()).value(index.column()).toDouble();
				int r= (int)(n*1000);
				int rm= r%10;
				r= r/10;
				n= r;
				if(rm >= 5) n= n/100+0.01;
				else n= n/100;
				return n;
			}
			if(index.column() == 5){
				double n= cc.value(index.row()).value(index.column()).toDouble();
				int r= (int)(n*100);
				int rm= r%10;
				r= r/10;
				n= r;
				if(rm >= 5) n= n/10+0.1;
				else n= n/10;
				return n;
			}
			return cc.value(index.row()).value(index.column());
		}
	}
	if( index.column() >1 && role == Qt::BackgroundRole ) return QBrush(QColor(255,255,0,128));
	return QVariant();
}

QVariant shoppingListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if(orientation == Qt::Horizontal){
		if(role == Qt::DisplayRole){
			switch(section){
			case 0: return tr("date");
			break;
			case 1: return tr("list");
			break;
			case 2: return tr("purchases count");
			break;
			case 3: return tr("total planned");
			break;
			case 4: return tr("total bought");
			break;
			case 5: return tr("average joy");
			break;
			default: return QAbstractTableModel::headerData(section, orientation, role);
			}
		}
	}else{
		;
	}
	return QAbstractTableModel::headerData(section, orientation, role);
}

bool shoppingListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	if(role == Qt::EditRole || role == Qt::DisplayRole){
		QVariant v= value.toString().trimmed();
		if(v == cc.value(index.row()).value(index.column())) return true;
		q.prepare(QString("UPDATE purchase SET "+fieldNames.at(index.column())+"=:V WHERE pDate=:D AND pList=:L"));
		q.bindValue(":D",formatDate(cc.value(index.row()).value(0)));
		q.bindValue(":L",cc.value(index.row()).value(1));
		if(index.column() == 0) q.bindValue(":V",formatDate(v));
		else q.bindValue(":V",v);
		if(!q.exec()) return reportErr(q);
		if(index.column() == 0 || index.column() ==1){
			q.prepare(QString("UPDATE listSettings SET "+fieldNames.at(index.column())+"=:N WHERE pDate=:D AND pList=:L"));
			q.bindValue(":D",formatDate(cc.value(index.row()).value(0)));
			q.bindValue(":L",cc.value(index.row()).value(1));
			if(index.column() == 0) q.bindValue(":N",formatDate(v));
			else q.bindValue(":N",v);
			q.exec();
		}
		if(index.column()==0){
			if(v.toDate()<wDateBegin || v.toDate()>wDateEnd){
				cc.removeAt(index.row());
				removeRows(index.row(),1);
				emit totalChanged();
			}else cc[index.row()].setValue(index.column(),v);
		}else cc[index.row()].setValue(index.column(),v);
	}
	emit dataChanged(index,index);
	return true;
}

Qt::ItemFlags shoppingListModel::flags(const QModelIndex & index) const
{
	Qt::ItemFlags f= Qt::ItemIsEnabled|(index.column() >1 ? Qt::NoItemFlags: Qt::ItemIsSelectable|Qt::ItemIsEditable);
	if(index.column()==1) f|=Qt::ItemIsTristate;
	return f;
}

bool shoppingListModel::insertRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginInsertRows(parent, row, row+count-1);
	endInsertRows();
	return true;
}

bool shoppingListModel::removeRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginRemoveRows(parent, row, row+count-1);
	endRemoveRows();
	return true;
}

void shoppingListModel::clear()
{
	beginResetModel();
	removeRows(0,rowCount());
	cc.clear();
	wDateBegin= QDate();
	wDateEnd= QDate();
	endResetModel();
}

void shoppingListModel::restore(const QDate dateBegin, const QDate dateEnd)
{
	clear();
	wDateBegin= dateBegin;
	wDateEnd= dateEnd;
	// get data from DB
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare("SELECT pDate,pList,count()as pCnt,sum(pPrcP*pCntP) as pCostP"
			  ",sum(pPrcB*pCntB) as pCost,avg(pJoy),avg(pDone) FROM purchase"
			  " WHERE pDate>=:DB AND pDate<=:DE GROUP BY pDate,pList");
	q.bindValue(":DB", wDateBegin.toString("yyyy-MM-dd"));
	q.bindValue(":DE", wDateEnd.toString("yyyy-MM-dd"));
	q.exec();
	while(q.next()) cc.append(QSqlRecord(q.record()));

	insertRows(0,rowCount());
}

bool shoppingListModel::rem(int row)
{
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare(QString("DELETE FROM purchase WHERE pDate=:D AND pList=:L"));
	q.bindValue(":D", cc.value(row).value(0).toString());
	q.bindValue(":L", cc.value(row).value(1).toString());
	if(q.exec()){
		cc.removeAt(row);
		return removeRows(row,1);
	}
	return true;
}

bool shoppingListModel::reportErr(QSqlQuery &q){
	qCritical()<< q.lastError().text();
	return false;
}

QString shoppingListModel::formatDate(const QVariant &v){
	if(v.canConvert(QVariant::Date)) return v.toDate().toString("yyyy-MM-dd");
	return QString();
}

